/**
 * @file    main.cpp
 * @author  wuhui1536@gmail.com
 * @date    2025-02-19
 * @brief   文件类型检测器 - 入口文件
 *
 * @details
 * 该程序用于加载 JSON 规则，并检测指定文件的类型。
 * 用户可以通过传入文件路径来检测其格式是否符合预期。
 *
 * @note
 * 需要提供 `file_signature_rules.json` 规则文件，并确保其格式正确。
 *
 */

#include "fileChecker.h"

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <cstdlib>  // for exit()
#include <cstring>  // for strcmp()
#include <getopt.h> // for getopt() to parse command-line arguments
#include <dirent.h> // for directory operations in C++98

using namespace std;

/**
 * @brief 打印程序的使用说明
 */
void printUsage(const char *programName)
{
    cout << "用法: " << programName << " [-r 规则文件] [-f 测试文件] [-a 测试目录] [-h]\n"
         << "  -r 规则文件   指定规则文件 (默认: file_signature_rules.json)\n"
         << "  -f 测试文件   指定单个测试文件 (可多次使用 -f 指定多个文件)\n"
         << "  -a 测试目录   指定要检测的目录 (必须提供目录路径)\n"
         << "  -h            显示帮助信息\n";
}

/**
 * @brief 获取指定目录中的所有文件
 * @param directory 目录路径
 * @return 文件名列表
 */
vector<string> getFilesInDirectory(const string &directory)
{
    vector<string> files;
    DIR *dir;
    struct dirent *ent;

    if ((dir = opendir(directory.c_str())) != NULL)
    {
        while ((ent = readdir(dir)) != NULL)
        {
            string filename = ent->d_name;
            // 忽略 "." 和 ".."
            if (filename != "." && filename != "..")
            {
                files.push_back(directory + "/" + filename);
            }
        }
        closedir(dir);
    }
    else
    {
        cerr << "错误: 无法打开目录 " << directory << endl;
        exit(1);
    }
    return files;
}

/**
 * @brief 测试给定文件列表的类型
 * @param files 文件路径列表
 * @param rulesFile 规则文件路径
 */
void testFiles(const vector<string> &files, const string &rulesFile)
{
    FileChecker fileChecker(rulesFile);

    for (size_t i = 0; i < files.size(); i++)
    {
        string fileType = fileChecker.matchFileType(files[i]);
        cout << "文件: " << files[i] << " - 类型: " << fileType << endl;
    }
}

/**
 * @brief 主函数 - 解析命令行参数并执行文件类型检测
 * @param argc 参数个数
 * @param argv 参数值
 * @return 程序执行结果
 */
int main(int argc, char *argv[])
{
    string rulesFile = "file_signature_rules.json"; // 默认规则文件
    string testPath;
    vector<string> filesToTest;
    bool allFilesFlag = false; // 是否测试所有文件

    // 使用 getopt 解析命令行参数
    int opt;
    while ((opt = getopt(argc, argv, "r:f:a:h")) != -1)
    {
        switch (opt)
        {
        case 'r': // 指定规则文件
            rulesFile = optarg;
            break;
        case 'f': // 指定单个测试文件
            filesToTest.push_back(optarg);
            break;
        case 'a': // 测试 "test" 目录下的所有文件
            testPath = optarg;
            allFilesFlag = true;
            break;
        case 'h': // 显示帮助信息
        default:
            printUsage(argv[0]);
            return 0;
        }
    }

    // 如果指定了 -a 选项，则测试目录下的所有文件
    if (!testPath.empty())
    {
        filesToTest = getFilesInDirectory(testPath);
    }

    // 如果没有指定文件，并且未使用 -a 选项，则报错并输出帮助信息
    if (filesToTest.empty() && !allFilesFlag)
    {
        printUsage(argv[0]);
        return 1;
    }

    // 执行文件检测
    testFiles(filesToTest, rulesFile);

    return 0;
}
